#include "mainwidget.h"
#include <QHostAddress>
#include <QMessageBox>
#include <QDebug>

mainWidget::mainWidget(QWidget *parent)
    : QWidget(parent)
{
    setWindowTitle(tr("UDP Server"));

    MsgLabel = new QLabel(tr("Msg :"), this);
    MsgEdit = new QTextEdit(this);
    closeBtn = new QPushButton(tr("Close"), this);

    mainLayout = new QVBoxLayout(this);
    mainLayout->addWidget(MsgLabel);
    mainLayout->addWidget(MsgEdit);
    mainLayout->addWidget(closeBtn);

    connect(closeBtn, SIGNAL(clicked()), this, SLOT(closeBtnClicked()));

    //创建并初始化客户端地址信息链表容器。
    ClientList = new QList<ClientAdressPort *>;
    ClientList->clear();

    port = 8888;    //初始化绑定端口数据
    udpSocket = new QUdpSocket(this);

    connect(udpSocket, SIGNAL(readyRead()), this, SLOT(msgRecv()));

    bool result = udpSocket->bind(port);
    if(!result)
    {
        //端口绑定失败，弹出消息框，通常失败原因是当前绑定的端口被占用。
        QMessageBox::information(this, tr("error"), tr("udp socket create error!"));
        return ;
    }

}

mainWidget::~mainWidget()
{
}

void mainWidget::closeBtnClicked()
{
    close();
}


void mainWidget::sendMsg(QString &sendmsg)
{
    if(ClientList->isEmpty())
    {
        qDebug() << "current not client!";
        return;
    }
    for(it = ClientList->begin(); it != ClientList->end(); ++it)
    {
        udpSocket->writeDatagram(sendmsg.toLatin1(), sendmsg.length(), (*it)->adress, (*it)->port);
    }
}

void mainWidget::msgRecv()
{
    QHostAddress recvAddress;
    int recvPort = 0;
    int ret = 0;
    while(udpSocket->hasPendingDatagrams())
    {
        ret = udpSocket->readDatagram((char *)&recvMsg, (qint64)sizeof(recvMsg), &recvAddress, (quint16 *)&recvPort);
        if(ret < 0)
        {
            //recv error
            memset(&recvMsg, 0, sizeof(recvMsg));
            return;
        }
        msgProcess(recvMsg, recvAddress, recvPort);
    }
}

bool mainWidget::isInList(QHostAddress &recvAddres, int recvPort)
{
    if(ClientList->isEmpty())
    {
        return false;
    }
    for(it = ClientList->begin(); it != ClientList->end(); ++it)
    {
        if((*it)->adress == recvAddres && (*it)->port == recvPort)
        {
            return true;
        }
    }
    return false;
}

int mainWidget::msgProcess(MSG_t &msg, QHostAddress &recvAddres, int recvPort)
{
    QString textString;
    switch (msg.key) {
    case LOGIN:
        doLogin(msg, recvAddres, recvPort);
        textString = QString(tr("Login: %1 ")).arg(msg.name);
        break;
    case CHAT:
        doChat(msg, recvAddres, recvPort);
        textString = QString(tr("chat: %1 : %2")).arg(msg.name).arg(msg.data);
        break;
    case QUIT:
        doQuit(msg, recvAddres, recvPort);
        textString = QString(tr("quit: %1 ")).arg(msg.name);
        break;
    default:
        //出错
        qDebug() << "recv msg key error!";
        MsgEdit->append(tr("recv msg key error!"));
        return -1;
    }
    MsgEdit->append(textString);
    return  0;
}

void mainWidget::doLogin(MSG_t &msg, QHostAddress &recvAddres, int recvPort)
{
    ClientAdressPort *client = new ClientAdressPort;
    client->adress = recvAddres;
    client->port = recvPort;
    ClientList->append(client);

    QString WelcomMsg = QString("Welcome %1 !").arg(msg.name);
    //向所有用户发送 欢迎消息
    sendMsg(WelcomMsg);
    MsgEdit->append(WelcomMsg);
}

void mainWidget::doChat(MSG_t &msg, QHostAddress &recvAddres, int recvPort)
{
    if(!isInList(recvAddres, recvPort))
    {
        qDebug() << "client not login!";
        QString errMsg = QString("Sorry, You are not login!");
        udpSocket->writeDatagram(errMsg.toLatin1(), errMsg.length(), recvAddres, recvPort);
        return ;
    }
    QString sendmsg = QString("%1 :").arg(msg.name) + QString(msg.data);
    sendMsg(sendmsg);
    MsgEdit->append(sendmsg);
}

void mainWidget::doQuit(MSG_t &msg, QHostAddress &recvAddres, int recvPort)
{
    if(!isInList(recvAddres, recvPort))
    {
        qDebug() << "client not login!";
        QString errMsg = QString("Sorry, You are not login!");
        udpSocket->writeDatagram(errMsg.toLatin1(), errMsg.length(), recvAddres, recvPort);
        return ;
    }
    QString sendmsg = QString("%1 quit chat!").arg(msg.name);
    sendMsg(sendmsg);
    MsgEdit->append(sendmsg);

    //遍历，去掉其中的退出客户端信息
    for(it = ClientList->begin(); it != ClientList->end(); ++it)
    {
        if( recvAddres == ((*it)->adress) && recvPort == ((*it)->port))
        {
            ClientAdressPort *quitClient = ClientList->at(it - ClientList->begin());
            ClientList->removeOne(*it);
            delete quitClient;
        }
    }
}
